package com.brokendust.client.api.module.image;

import com.brokendust.client.api.util.LocationUtil;
import com.brokendust.client.api.util.image.ImageControl;
import com.brokendust.client.config.module.image.ImageEntityJson;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderState;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3f;

public class ImageEntity {
    private static RenderState.AlphaState ALPHA;
    private static RenderState.LightmapState ENABLE_LIGHTMAP;
    private static RenderState.TransparencyState TRANSLUCENT;

    static {
        ALPHA = new RenderState.AlphaState(0.003921569f);
        ENABLE_LIGHTMAP = new RenderState.LightmapState(true);
        TRANSLUCENT = new RenderState.TransparencyState("translucent", () -> {
            RenderSystem.enableBlend();
            RenderSystem.defaultBlendFunc();
        }, RenderSystem::disableBlend);
    }

    private String uuidString;
    private String image;
    private float scale;
    private float width;
    private float height;
    private double locationHeight;
    private double locationAngle;
    private double locationDistance;
    private int direction;
    private float rotateX;
    private float rotateY;
    private float rotateZ;
    private int autoRotationX;
    private int autoRotationY;
    private int autoRotationZ;

    public ImageEntity(ImageEntityJson imageEntityJson) {
        this.image = imageEntityJson.getImage();
        this.uuidString = imageEntityJson.getUuidString();
        this.scale = imageEntityJson.getScale();
        this.width = imageEntityJson.getWidth();
        this.height = imageEntityJson.getHeight();
        this.locationHeight = imageEntityJson.getLocationHeight();
        this.locationAngle = imageEntityJson.getLocationAngle();
        this.locationDistance = imageEntityJson.getLocationDistance();
        this.direction = imageEntityJson.getDirection();
        this.rotateX = imageEntityJson.getRotateX();
        this.rotateY = imageEntityJson.getRotateY();
        this.rotateZ = imageEntityJson.getRotateZ();
        this.autoRotationX = imageEntityJson.getAutoRotationX();
        this.autoRotationY = imageEntityJson.getAutoRotationY();
        this.autoRotationZ = imageEntityJson.getAutoRotationZ();
    }

    protected static RenderType slide(ResourceLocation loc) {
        RenderType.State renderState = RenderType.State.builder()
                .setAlphaState(ImageEntity.ALPHA)
                .setLightmapState(ImageEntity.ENABLE_LIGHTMAP)
                .setTransparencyState(ImageEntity.TRANSLUCENT)
                .setTextureState(new RenderState.TextureState(loc, false, true))
                .createCompositeState(false);
        return RenderType.create("slide_show", DefaultVertexFormats.POSITION_COLOR_TEX_LIGHTMAP, 7, 256, false, true, renderState);
    }

    public void renderImage(PlayerEntity player, MatrixStack matrixStackIn, IRenderTypeBuffer buffer) {
        String playerUUIDString = player.getStringUUID();
        if (!this.uuidString.equals(playerUUIDString)) {
            return;
        }
        if (this.rotateX >= 360.0f) {
            this.rotateX = 0.0f;
        }
        if (this.rotateY >= 360.0f) {
            this.rotateY = 0.0f;
        }
        if (this.rotateZ >= 360.0f) {
            this.rotateZ = 0.0f;
        }
        float fontAngle = player.getRotationVector().y % 360.0f;
        double lookAngle = (player.getRotationVector().y - 90.0f + this.locationAngle) % 360.0;
        double[] lookAngleLocation = LocationUtil.rotateXYZ(0.0, lookAngle, 0.0, new double[]{0.0, 0.0, 0.0}, this.locationDistance);
        matrixStackIn.pushPose();
        matrixStackIn.scale(this.scale, this.scale, this.scale);
        matrixStackIn.translate(lookAngleLocation[0], this.locationHeight, lookAngleLocation[2] * -1.0);
        if (this.rotateX > 0.0f) {
            matrixStackIn.mulPose(Vector3f.XP.rotationDegrees(this.rotateX));
        } else {
            matrixStackIn.mulPose(Vector3f.XN.rotationDegrees(this.rotateX * -1.0f));
        }
        if (this.rotateY > 0.0f) {
            matrixStackIn.mulPose(Vector3f.YP.rotationDegrees(this.rotateY));
        } else {
            matrixStackIn.mulPose(Vector3f.YN.rotationDegrees(this.rotateY * -1.0f));
        }
        if (this.rotateZ > 0.0f) {
            matrixStackIn.mulPose(Vector3f.YP.rotationDegrees(this.rotateZ));
        } else {
            matrixStackIn.mulPose(Vector3f.YN.rotationDegrees(this.rotateZ * -1.0f));
        }
        Matrix4f matrix4f = matrixStackIn.last().pose();
        this.renderHorizontal(buffer, matrix4f, this.width, this.height, this.direction);
        matrixStackIn.popPose();
        if (this.autoRotationX > 0) {
            this.rotateX += this.autoRotationX;
        }
        if (this.autoRotationY > 0) {
            this.rotateY += this.autoRotationY;
        }
        if (this.autoRotationZ > 0) {
            this.rotateZ += this.autoRotationZ;
        }
    }

    private IVertexBuilder renderHorizontal(IRenderTypeBuffer buffer, Matrix4f matrix, float width, float height, int direction) {
        IVertexBuilder builder = buffer.getBuffer(slide(ImageControl.getResourceLocation(this.image)));
        int red = 255;
        int green = 255;
        int blue = 255;
        int alpha = 255;
        int light = 15728640;
        width /= 2.0f;
        height /= 2.0f;
        float a = 0.0f;
        float b = 0.0f;
        float c = 1.0f;
        float d = 0.0f;
        float e = 1.0f;
        float f = 1.0f;
        float g = 0.0f;
        float h = 1.0f;
        if (direction == 2) {
            a = 1.0f;
            b = 0.0f;
            c = 1.0f;
            d = 1.0f;
            e = 0.0f;
            f = 1.0f;
            g = 0.0f;
            h = 0.0f;
        }
        if (direction == 3) {
            a = 0.0f;
            b = 1.0f;
            c = 1.0f;
            d = 1.0f;
            e = 1.0f;
            f = 0.0f;
            g = 0.0f;
            h = 0.0f;
        }
        if (direction == 4) {
            a = 0.0f;
            b = 0.0f;
            c = 0.0f;
            d = 1.0f;
            e = 1.0f;
            f = 1.0f;
            g = 1.0f;
            h = 0.0f;
        }
        builder.vertex(matrix, -width, 0.00390625f, height).color(red, green, blue, alpha).uv(a, b).overlayCoords(light).endVertex();
        builder.vertex(matrix, width, 0.00390625f, height).color(red, green, blue, alpha).uv(c, d).overlayCoords(light).endVertex();
        builder.vertex(matrix, width, 0.00390625f, -height).color(red, green, blue, alpha).uv(e, f).overlayCoords(light).endVertex();
        builder.vertex(matrix, -width, 0.00390625f, -height).color(red, green, blue, alpha).uv(g, h).overlayCoords(light).endVertex();
        builder.vertex(matrix, -width, -0.00390625f, -height).color(red, green, blue, alpha).uv(g, h).overlayCoords(light).endVertex();
        builder.vertex(matrix, width, -0.00390625f, -height).color(red, green, blue, alpha).uv(e, f).overlayCoords(light).endVertex();
        builder.vertex(matrix, width, -0.00390625f, height).color(red, green, blue, alpha).uv(c, d).overlayCoords(light).endVertex();
        builder.vertex(matrix, -width, -0.00390625f, height).color(red, green, blue, alpha).uv(a, b).overlayCoords(light).endVertex();
        return builder;
    }
}
